#include "sampler/sampler.h"
#include "sampler/map.h"
#include "datamidi.h"
#include <sndfile.h>
#include"sampler/polyphonychannel.h"
#include"sampler/samplerecord.h"


Sampler::Sampler() :
    map_(NULL), list_(NULL) {




    //    sampleTable.append (new SampleRecord(0x1, k_path+"stick_Woody.flac", bufsize));
    //    sampleTable.append (new SampleRecord(0x2, k_path+"clap_Dry_c.flac"), bufsize);
    //    sampleTable.append (new SampleRecord(0x3, k_path+"misc_Cowbell.flac"), bufsize);

}

Sampler::~Sampler(){
  delete map_;
}

void Sampler::setData(PData data){
    ports_ = data;
    bufsize_= data->size;
    map_ = new Map(bufsize_);
    const QString k_path = "/usr/share/hydrogen/data/drumkits/GMkit/";

    map_->loadSample(sampler::Note(0,0),
                     sampler::Note(9,127), 0,
                     k_path + "misc_Cowbell.flac");

    map_->loadSample(sampler::Note(10,0),
                     sampler::Note(19,127), 0,
                     k_path + "stick_Woody.flac");

    map_->loadSample(sampler::Note(20,0),
                     sampler::Note(29,127), 0,
                     k_path + "clap_Dry_c.flac");
}

void Sampler::process(){
    using namespace sampler;

    gl::PcmSampleType * out = ports_->outputs[0];
    foreach(TimedMidiData mididata, *list_ ){
        //gl::log("SMP: mididata");
        const char & note = mididata.first->data()[1];
        const char & velocity = mididata.first->data()[2];
        gl::TicksTime & position = mididata.second;
        Map::MapElement & map_element = map_->element(note);
        SampleRecord * sample = map_element.sample;
        gl::log("SMP: note %1", note);
        if (NULL == sample) {
            gl::log("SMP: sample is NULL");
            continue; }
        PolyphonyChannel * channel = map_element.polyphonyChannel;
        if (NULL == channel) {channel = map_->getFreeChannel();
            map_element.polyphonyChannel = channel;}

        Q_ASSERT (sample->file() != NULL);        
        channel->setNote(sample->file(), Note(note, velocity), position);
    }

    memset(out, 0, bufsize_ * sizeof(gl::PcmSampleType));

    foreach (PolyphonyChannel * pc, map_->currentChannels_){
        Q_ASSERT(pc != NULL);
        bool isActive;
        const gl::PcmSampleType * buf = pc->process(isActive);
        for (int i=0; i < bufsize_; ++i) out[i] += buf[i];
        if (!isActive) map_->setChannelFree(pc);
    }

    memcpy(ports_->outputs[1], ports_->outputs[0],
           bufsize_ * sizeof(gl::PcmSampleType));
}

